
/** findComponentUpward  由一个组件，向上找到最近的指定组件
 *  @param { context：'当前上下文'（一般为this）, componentName: '组件名字'}
 */
function findComponentUpward (context, componentName) {
    let parent = context.$parent;
    let name = parent.$options.name;

    while (parent && (!name || [componentName].indexOf(name) < 0)) {
        parent = parent.$parent;  // 不断向上覆盖当前的parent对象
        if (parent) {
            name = parent.$options.name;
        }
    }

    return parent;  // 返回找到最近的一个组件实例
}

export { findComponentUpward };


/** findComponentsUpward  由一个组件，向上找到所有的指定组件
 *  @param { context：'当前上下文'（一般为this）, componentName: '组件名字'}
 *  这个使用场景较少，一般只用在递归组件里面。
 */
function findComponentsUpward (context, componentName) {
    let parents = [];
    const parent = context.$parent;

    if (parent) {
        if (parent.$options.name === componentName) {
            return parents.push(parent);
        }
        return parents.concat(findComponentUpward(parent, componentName));
    } else {
        return [];
    }
}

export { findComponentsUpward };


/** findComponentDownward  由一个组件，向下找到最近的指定组件
 *  @param { context：'当前上下文'（一般为this）, componentName: '组件名字'}
 */
function findComponentDownward (context, componentName) {
    const childrens = context.$children;
    let children = null;

    if (childrens.length) {
        for (const child of childrens) {
            const name = child.$options.name;

            if (name === componentName) {
                children = child;
                break;
            } else {
                children = findComponentDownward(child, componentName);
                if (children) break;
            }
        }
    }
    return children;
}

export { findComponentDownward };

/** findComponentsDownward  由一个组件，向下找到所有的指定组件
 *  @param { context：'当前上下文'（一般为this）, componentName: '组件名字'}
 *  这里巧妙使用 reduce 做累加器，并用递归将找到的组件合并为一个数组并返回
 */
function findComponentsDownward (context, componentName) {
    return context.$children.reduce((components, child) => {
        if (child.$options.name === componentName) components.push(child);
        const foundChilds = findComponentsDownward(child, componentName);
        return components.concat(foundChilds);
    }, []);
}

export { findComponentsDownward };



/** findBrothersComponents  由一个组件，找到指定组件的兄弟组件
 *  @param { context：'当前上下文'（一般为this）, componentName: '组件名字', exceptMe: '是否把本身除外'}
 */
function findBrothersComponents (context, componentName, exceptMe = true) {
    let res = context.$parent.$children.filter(item => {
        return item.$options.name === componentName;
    });
    let index = res.findIndex(item => item._uid === context._uid);
    if (exceptMe) res.splice(index, 1);
    return res;
}

export { findBrothersComponents };